#pragma once

#include <pthread.h>
#include <functional>
#include "Protocal.hpp"
#include "Sock.hpp"
#include "Log.hpp"
#include "Util.hpp"

using namespace protocal_ns;

using cb_t = std::function<Request(const std::string &str)>;

class ns_client
{
public:
    ns_client(std::string serverIp, uint16_t serverPort, cb_t cb)
        : _serverIp(serverIp), _serverPort(serverPort), _cb(cb)
    {
    }

    void InitClient()
    {
        sock.Socket();
        sock.Connect(_serverIp, _serverPort);
    }

    void start()
    {
        std::string inbuffer;
        while (true)
        {
            std::string message;
            std::cin >> message;

            Request req = _cb(message);

            // 1.序列化
            std::string res;
            req.Serialize(&res);

            // 2.添加报头
            res = AddHeader(res);

            // 3.发送
            send(sock.Fd(), res.c_str(), res.size(), 0);

        START:
            // 4.获取结果
            std::string package;
            int n = ReadPackage(sock.Fd(), inbuffer, &package);
            if (n == 0)
                goto START;
            else if (n < 0)
                break;
            else
            {
                // 1.去除报头
                package = RemoveHeader(package, n);

                // 2.反序列化
                Reponse rep;
                rep.DeSerialize(package);

                // 3.输出结果
                std::cout << "result : " << rep._result << " exit_code : " << rep._exit_code << std::endl;
            }
        }
    }

    ~ns_client()
    {
    }

private:
    Sock sock;
    std::string _serverIp;
    uint16_t _serverPort;
    cb_t _cb;
};
